#pragma once

#include "../muduo_source/server.hpp"
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <regex>

std::unordered_map<int, std::string> _state_msg =
    {
        {100, "Continue"},
        {101, "Switching Protocol"},
        {102, "Processing"},
        {103, "Early Hints"},
        {200, "OK"},
        {201, "Created"},
        {202, "Accepted"},
        {203, "Non-Authoritative Information"},
        {204, "No Content"},
        {205, "Reset Content"},
        {206, "Partial Content"},
        {207, "Multi-Status"},
        {208, "Already Reported"},
        {226, "IM Used"},
        {300, "Multiple Choice"},
        {301, "Moved Permanently"},
        {302, "Found"},
        {303, "See Other"},
        {304, "Not Modified"},
        {305, "Use Proxy"},
        {306, "unused"},
        {307, "Temporary Redirect"},
        {308, "Permanent Redirect"},
        {400, "Bad Request"},
        {401, "Unauthorized"},
        {402, "Payment Required"},
        {403, "Forbidden"},
        {404, "Not Found"},
        {405, "Method Not Allowed"},
        {406, "Not Acceptable"},
        {407, "Proxy Authentication Required"},
        {408, "Request Timeout"},
        {409, "Conflict"},
        {410, "Gone"},
        {411, "Length Required"},
        {412, "Precondition Failed"},
        {413, "Payload Too Large"},
        {414, "URI Too Long"},
        {415, "Unsupported Media Type"},
        {416, "Range Not Satisfiable"},
        {417, "Expectation Failed"},
        {418, "I'm a teapot"},
        {421, "Misdirected Request"},
        {422, "Unprocessable Entity"},
        {423, "Locked"},
        {424, "Failed Dependency"},
        {425, "Too Early"},
        {426, "Upgrade Required"},
        {428, "Precondition Required"},
        {429, "Too Many Requests"},
        {431, "Request Header Fields Too Large"},
        {451, "Unavailable For Legal Reasons"},
        {501, "Not Implemented"},
        {502, "Bad Gateway"},
        {503, "Service Unavailable"},
        {504, "Gateway Timeout"},
        {505, "HTTP Version Not Supported"},
        {506, "Variant Also Negotiates"},
        {507, "Insufficient Storage"},
        {508, "Loop Detected"},
        {510, "Not Extended"},
        {511, "Network Authentication Required"}};

std::unordered_map<std::string, std::string> _mime_msg =
    {
        {".aac", "audio/aac"},
        {".abw", "application/x-abiword"},
        {".arc", "application/x-freearc"},
        {".avi", "video/x-msvideo"},
        {".azw", "application/vnd.amazon.ebook"},
        {".bin", "application/octet-stream"},
        {".bmp", "image/bmp"},
        {".bz", "application/x-bzip"},
        {".bz2", "application/x-bzip2"},
        {".csh", "application/x-csh"},
        {".css", "text/css"},
        {".csv", "text/csv"},
        {".doc", "application/msword"},
        {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
        {".eot", "application/vnd.ms-fontobject"},
        {".epub", "application/epub+zip"},
        {".gif", "image/gif"},
        {".htm", "text/html"},
        {".html", "text/html"},
        {".ico", "image/vnd.microsoft.icon"},
        {".ics", "text/calendar"},
        {".jar", "application/java-archive"},
        {".jpeg", "image/jpeg"},
        {".jpg", "image/jpeg"},
        {".js", "text/javascript"},
        {".json", "application/json"},
        {".jsonld", "application/ld+json"},
        {".mid", "audio/midi"},
        {".midi", "audio/x-midi"},
        {".mjs", "text/javascript"},
        {".mp3", "audio/mpeg"},
        {".mpeg", "video/mpeg"},
        {".mpkg", "application/vnd.apple.installer+xml"},
        {".odp", "application/vnd.oasis.opendocument.presentation"},
        {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
        {".odt", "application/vnd.oasis.opendocument.text"},
        {".oga", "audio/ogg"},
        {".ogv", "video/ogg"},
        {".ogx", "application/ogg"},
        {".otf", "font/otf"},
        {".png", "image/png"},
        {".pdf", "application/pdf"},
        {".ppt", "application/vnd.ms-powerpoint"},
        {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
        {".rar", "application/x-rar-compressed"},
        {".rtf", "application/rtf"},
        {".sh", "application/x-sh"},
        {".svg", "image/svg+xml"},
        {".swf", "application/x-shockwave-flash"},
        {".tar", "application/x-tar"},
        {".tif", "image/tiff"},
        {".tiff", "image/tiff"},
        {".ttf", "font/ttf"},
        {".txt", "text/plain"},
        {".vsd", "application/vnd.visio"},
        {".wav", "audio/wav"},
        {".weba", "audio/webm"},
        {".webm", "video/webm"},
        {".webp", "image/webp"},
        {".woff", "font/woff"},
        {".woff2", "font/woff2"},
        {".xhtml", "application/xhtml+xml"},
        {".xls", "application/vnd.ms-excel"},
        {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
        {".xml", "application/xml"},
        {".xul", "application/vnd.mozilla.xul+xml"},
        {".zip", "application/zip"},
        {".3gp", "video/3gpp"},
        {".3g2", "video/3gpp2"},
        {".7z", "application/x-7z-compressed"}};

struct Util
{
    static int Split(std::string src, std::string sep, std::vector<std::string> *ret)
    {
        int offset = 0;
        while (offset < src.size())
        {
            int pos = src.find(sep, offset);
            if (pos == std::string::npos)
            {
                ret->push_back(src.substr(offset));
                return ret->size();
            }
            //
            if (pos - offset != 0)
            {
                ret->push_back(src.substr(offset, pos - offset));
            }

            offset = pos + sep.size();
        }
        return ret->size();
    }
     
    static bool ReadFile(std::string &filename, std::string *buf)      //将文件内容读取得到buf中
    {
        std::ifstream ifs(filename.c_str(), std::ios::binary);
        if (ifs.is_open() == false)
        {
            ERR_LOG("open file is error");
            return false;
        }

        ifs.seekg(0, ifs.end);
        int size = ifs.tellg();
        ifs.seekg(0, ifs.beg);
        (*buf).resize(size);
        ifs.read(&(*buf)[0], size);
        if (ifs.good() == false)
        {
            ERR_LOG("read file is error");
            ifs.close();
            return false;
        }
        return true;
    }

    static bool WriteFile(std::string filename, const std::string &buf)
    {
        std::ofstream ofs(filename.c_str(), std::ios::binary | std::ios::trunc);
        if (ofs.is_open() == false)
        {
            ERR_LOG("open file is error");
            return false;
        }
        ofs.write(buf.c_str(), buf.size());
        if (ofs.good() == false)
        {
            ERR_LOG("write file is error");
            return false;
        }
        return true;
    }

    // URL解码

    static std::string UrlEncode(const std::string url, bool convert_space_to_puls)
    {
        std::string ret;

        for (auto &e : url)
        {
            if (e == '.' || e == '~' || e == '-' || isalnum(e))
            {
                ret += e;
                continue;
            }
            if (e == ' ' && convert_space_to_puls == true)
            {
                ret += '+';
            }
            else
                ret += ' ';
            char tmp[4] = {0};
            snprintf(tmp, sizeof(tmp), "%%%02x", e);
            ret += tmp;
        }
        return ret;
    }

    static int HEXTOI(char a)
    {
        if (a >= '0' && a <= '9')
            return a - '0';
        else if (a >= 'a' && a <= 'z')
            return a - 'a' + 10;
        else if (a >= 'A' && a <= 'Z')
            return a - 'A' + 10;
        return -1;
    }

    static std::string UrlDecode(const std::string url, bool convert_space_to_plus)
    {
        std::string ret;
        for (int i = 0; i < url.size(); i++)
        {
            if (ret[i] == '+' && convert_space_to_plus)
            {
                ret += ' ';
                continue;
            }
            //
            if (url[i] == '%' && i + 2 < url.size())
            {
                char v1 = HEXTOI(url[i + 1]);
                char v2 = HEXTOI(url[i + 2]);
                char v = (v2 << 4) + v1;
                ret += v;
                i += 2;
                continue;
            }
            ret += url[i];
        }
        return ret;
    }

    // 获取响应状态码
    static std::string StateDesc(int state)
    {
        auto it = _state_msg.find(state);
        if (it == _state_msg.end())
        {
            return "Unknown";
        }
        return it->second;
    }

    //
    static std::string GetMIME(std::string str)
    {
        int pos = str.find('.');
        std::string tmp = str.substr(pos);

        auto it = _mime_msg.find(tmp);
        if (it == _mime_msg.end())
        {
            return "application/octet-stream";
        }
        else
            return it->second;
    }

    static bool Is_Dir(std::string filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(), &st);
        if (ret < 0)
        {
            ERR_LOG("stat error");
            return false;
        }

        return S_ISDIR(st.st_mode);
    }

    static bool Is_Reg(std::string filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(), &st);
        if (ret < 0)
        {
            return false;
        }
        return S_ISREG(st.st_mode);
    }

    static bool ValidPath(std::string path) // 判断当前目录是否是一个有效目录： 遇到..就深度减一， 否则就加一。 如果小于0了， 说明
                                            // 脱离了web目录， 直接返回。
    {
        std::vector<std::string> act;
        int ret = Util::Split(path, "/", &act);
        int level = 0;
        for (auto &str : act)
        {
            if (str == "..")
            {
                level--;
                if (level < 0)
                    return false;
                continue;
            }
            else
                level++;
        }
        return true;
    }
};

class HttpRequest
{
public:
    std::string _method;                                   // 请求方法
    std::string _path;                                     // 资源路径
    std::string _version;                                  // 协议版本
    std::string _body;                                     // 请求正文
    std::smatch _matches;                                  // 资源路径的正则提取数据
    std::unordered_map<std::string, std::string> _params;  // 字符串提取
    std::unordered_map<std::string, std::string> _headers; // 头部字段

public:
    std::string &Getbody()
    {
        return _body;
    }
    void Reset()
    {
        _method.clear();
        _path.clear();
        _version.size();
        _body.size();
        std::smatch matches;
        matches.swap(_matches);
        _params.clear();
        _headers.clear();
    }

    bool HasHeader(std::string key)
    {
        auto it = _headers.find(key);
        if (it == _headers.end())
            return false;
        return true;
    }

    bool SetHeader(std::string key, std::string val)
    {
        if (HasHeader(key))
            return false;
        _headers.insert({key, val});
        return true;
    }

    std::string GetHeader(std::string key)
    {
        if (HasHeader(key))
            return _headers[key];
        else
            return "";
    }

    bool HasParam(std::string key)
    {
        auto it = _params.find(key);
        if (it == _params.end())
            return false;
        return true;
    }

    bool SetParam(std::string key, std::string val)
    {
        if (HasParam(key))
            return false;
        _params.insert({key, val});
        return true;
    }

    std::string GetParam(std::string key)
    {
        if (HasParam(key))
            return _headers[key];
        else
            return "";
    }

    uint64_t GetContentLength()
    {
        if (HasHeader("Content-Length") == false)
            return false;
        std::string ret = GetHeader("Content-Length");
        return std::stol(ret);
    }

    bool IsColse()
    {
        if ((HasHeader("Connection") == true) && (GetHeader("Connection") == "keep-alive"))
            return false;
        return true;
    }
};

class HttpResponse
{
private:
    int _state;
    bool _redirect_flag;
    std::string _redirect_url;
    std::string _body;
    std::unordered_map<std::string, std::string> _headers;

public:
    HttpResponse(int state = 200)
        :_state(state),
        _redirect_flag(false)
    {}
    std::string &GetBody()
    {
        return _body;
    }
    int &GetState()
    {
        return _state;
    }

    bool Is_Redirect_flag()
    {
        return _redirect_flag;
    }

    std::string GetRedirecURL()
    {
        return _redirect_url;
    }

    void Reset()
    {
        _state = 0;
        _redirect_flag = 0;
        _redirect_url.clear();
        _body.clear();
        _headers.clear();
    }

    std::unordered_map<std::string, std::string> GetHeaders()
    {
        return _headers;
    }

    bool HasHeader(std::string key)
    {
        auto it = _headers.find(key);
        if (it == _headers.end())
            return false;
        return true;
    }

    bool SetHeader(std::string key, std::string val)
    {
        if (HasHeader(key))
            return false;
        _headers.insert({key, val});
        return true;
    }

    std::string GetHeader(std::string key)
    {
        if (HasHeader(key))
            return _headers[key];
        else
            return "";
    }

    void SetContent(std::string body, std::string type = "text/html")
    {
        _body = body;
        std::string str("Content-type");
        SetHeader(str, type);
    }

    void SetRedirectUrl(std::string url, int state)
    {
        _redirect_flag = true;
        _redirect_url = url;
        _state = state;
    }

    bool IsColse()
    {
        if ((HasHeader("Connection") == true) && (GetHeader("Connection") == "keep-alive"))
            return false;
        return true;
    }
};

typedef enum
{
    RECV_HTTP_ERROR, // 错误
    RECV_HTTP_LINE,  // 请求行
    RECV_HTTP_HEAD,  // 头部
    RECV_HTTP_BODY,  // 身体
    RECV_HTTP_OVER   // 结束

} HttpRecvState;
#define MAXRECVLINESIZE 8096
class HttpContent
{
private:
    int _resp_state;           // 响应状态码
    HttpRecvState _recv_state; // 请求的接收状态
    HttpRequest _request;      // 接收到的请求

public:
    /*获取一行信息*/
    bool RecvHttpLine(Buffer *buf)
    {
        std::string line = buf->GetLineAndMove();

        if (line.size() == 0)
        {
            if (buf->ReadAbleSize() > MAXRECVLINESIZE)
            {
                _resp_state = 414; // URL TO LONG
                _recv_state = RECV_HTTP_ERROR;
                return false;
            }
            return true; // 其他情况说明没有一行信息了
        }

        if (line.size() > MAXRECVLINESIZE)
        {
            _resp_state = 414; // URL TO LONG
            _recv_state = RECV_HTTP_ERROR;
            return false;
        }

        bool ret = PraseHttpLine(line);
        if (ret == false)
        {
            return false;
        }
        _recv_state = RECV_HTTP_HEAD;
        return true;
    }

    bool PraseHttpLine(std::string line)
    {
        std::regex e("(GET|PUT|DELETE|POST|HEAD) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?");
        std::smatch match;
        int ret = std::regex_match(line, match, e);
        if (ret < 0)
        {
            ERR_LOG("regex error");
            _resp_state = 400;             // BAD REQUEST
            _recv_state = RECV_HTTP_ERROR; // 接收请求行出错
            return false;
        }

        std::string method = match[1];              // 获取请求方法
        _request._method = method;
        std::string path = Util::UrlDecode(match[2], false);                // 获取资源路径
        _request._path = path;
        std::string version = match[4];             // 获取协议版本
        _request._version = version;
        std::vector<std::string> query_string_arry; // 查询字符串
        std::string query_string = match[3];        // 获取所有的查询字符串
        Util::Split(query_string, "&", &query_string_arry);

        for (auto &e : query_string_arry)
        {
            size_t pos = e.find("=");
            if (pos == std::string::npos)
            {
                _resp_state = 400;
                _recv_state = RECV_HTTP_ERROR;
                return false;
            }
            std::string key = Util::UrlDecode(e.substr(0, pos), true);
            std::string val = Util::UrlDecode(e.substr(pos + 1), true);
            _request.SetParam(key, val);
        }

        return true;
    }

    bool RecvHttpHead(Buffer *buf)
    {
        if (_recv_state != RECV_HTTP_HEAD)
            return false;

        while (1)
        {
            std::string line = buf->GetLineAndMove();
            if (line.size() == 0)
            {
                if (buf->ReadAbleSize() > MAXRECVLINESIZE)
                {
                    _resp_state = 414;
                    _recv_state = RECV_HTTP_ERROR;
                    return false;
                }
                return true; // 不足一行， 说明请求不完整
            }
            if (line.size() > MAXRECVLINESIZE)
            {
                _resp_state = 414;
                _recv_state = RECV_HTTP_ERROR;
                return false;
            }
            if (line == "\n" || line == "\r\n")
                break;
            int ret = PraseHttpHead(line);
            if (ret < 0)
            {
                return false;
            }
        }
        _recv_state = RECV_HTTP_BODY;
        return true;
    }
    bool PraseHttpHead(std::string line)
    {
        if (line.back() == '\n')
            line.pop_back();
        if (line.back() == '\r')
            line.pop_back();
            
        int pos = line.find(": ");
        if (pos == std::string::npos)
        {
            _resp_state = 400;
            _recv_state = RECV_HTTP_ERROR;
            return false;
        }
        std::string key = line.substr(0, pos);
        std::string val = line.substr(pos + 2);
        _request.SetHeader(key, val);
        return true;
    }

    bool RecvHttpBody(Buffer *buf)
    {
        size_t size = _request.GetContentLength();
        if (size == 0)
        {
            _recv_state = RECV_HTTP_OVER;
            return true;
        }
        int real_len = size - _request.Getbody().size();
        if (buf->ReadAbleSize() >= real_len)
        {
            _request.Getbody().append((char *)buf->ReadPosition(), real_len);
            buf->ReaderMove(real_len);
            _recv_state = RECV_HTTP_OVER;
            return true;
        }
        else
        {
            _request.Getbody().append((char *)buf->ReadPosition(), buf->ReadAbleSize());
            buf->ReaderMove(buf->ReadAbleSize());
            return true;
        }
    }

public:
    HttpContent()
        :_resp_state(200),
        _recv_state(RECV_HTTP_LINE)
    {}

    int GetRespState()
    {
        return _resp_state;
    }

    HttpRecvState GetRecvState()
    {
        return _recv_state;
    }

    HttpRequest &GetHttpRequest()
    {
        return _request;
    }

    // 接受并解析HTTP请求
    void RecvHttpRequest(Buffer *buf)
    {
        switch (_recv_state)
        {
            case RECV_HTTP_LINE:
                RecvHttpLine(buf);
            case RECV_HTTP_HEAD:
                RecvHttpHead(buf);
            case RECV_HTTP_BODY:
                RecvHttpBody(buf);
        }
    }

    void Reset()
    {
        _resp_state = 200;
        _recv_state = RECV_HTTP_LINE;
        _request.Reset();
    }
};


class HttpServer
{
public:
    using Handler = std::function<void(const HttpRequest&, HttpResponse *)>;
    using Handlers = std::vector<std::pair<std::regex, Handler>>;
private:
    Handlers _get_route;
    Handlers _post_route;
    Handlers _put_route;
    Handlers _delete_route; 
    std::string _basedir;                   //根目录
    TcpServer _server;    

    void ErrorHandler(HttpResponse *rsp)
    {
        std::string ret;
        ret += "<html>";
        ret += "<head>";
        ret += "<meta content='text/html; charset=utf-8' http-equiv='content-type'/>";
        ret += "</head>";
        ret += "<body>";
        ret += "<h1>";
        ret += std::to_string(rsp->GetState());
        ret += " ";
        ret += Util::StateDesc(rsp->GetState()); 
        ret += "</h1>";
        ret += "</body>";
        ret += "</html>";
        rsp->SetContent(ret, "text/html");
    }

    void WriteResponse(const PtrConn &conn, HttpRequest &req, HttpResponse *resp)
    {
        
        if (req.IsColse() == true)
        {
            resp->SetHeader("Connection", "close");
        }
        else 
        {
            resp->SetHeader("Connection", "keep-alive");
        }
        
        if (resp->GetBody().empty() == false && resp->HasHeader("Content-Length") == false)
        {
            resp->SetHeader("Content-Length", std::to_string((int)(resp->GetBody().size())));
        }
        
        if (resp->GetBody().empty() == false && resp->HasHeader("Content-type") == false)
        {
            resp->SetHeader("Content-type", "application/octet-stream");
        }
        
        if (resp->Is_Redirect_flag() == true)
        {
            resp->SetHeader("Location", resp->GetRedirecURL());
        }
        //将resp中的要素格式化进行组织
        std::stringstream sstr;
        sstr << req._version << " " << std::to_string(resp->GetState()) << " " << Util::StateDesc(resp->GetState()) << "\r\n";
        for (auto &e : resp->GetHeaders())
        {
            sstr << e.first << ": " << e.second << "\r\n";
        }
        sstr << "\r\n";
        sstr << resp->GetBody();
        DBG_LOG("%s", sstr.str().c_str());
        
        conn->Send((char*)sstr.str().c_str(), sstr.str().size());
    }

    bool IsFileHandler(HttpRequest &req)
    {
        if (_basedir.empty() == false)
        {
            return false;
        }

        if (req._method != "GET" || req._method != "HEAD") 
        {
            return false;
        }

        if (!Util::ValidPath(req._path))
        {
            return false;
        }

        std::string req_path = _basedir + req._path;

        //判断是否是普通文件， 判断请求末尾是不是/
        if (req_path.back() == '/')
        {
            req_path.append("index.html");
        }

        if (!Util::Is_Reg(req_path))
        {
            return false;
        }
        //走到这里， 说明req_path里面是静态资源路径， 可以访问。 注意要把没写出的默认文件名添加上
        req._path = req_path;
        return true;
    }

    bool FileHandler(HttpRequest &req, HttpResponse *resp)
    {
        int ret = Util::ReadFile(req._path, &(resp->GetBody()));
        if (ret < 0)
        {
            return false;
        }

        //
        std::string mime = Util::GetMIME(req._path);
        resp->SetHeader("Content-type:", mime);
        return true;
    }

    bool Dispatcher(const HttpRequest &req, HttpResponse *resp, Handlers handlers)
    {
        for (auto &handler : handlers)
        {
            //e里面的first就是解析格式， second就是对应的处理的方法
            auto e = handler.first;
            auto functor = handler.second;
            std::smatch match;
            int ret = std::regex_match(req._path, match, e);
            if (ret < 0)
            {
                continue;
            }
            functor(req, resp);
            return true;
        }

        resp->GetState() = 404;
        return false;
    }

    bool Route(HttpRequest &req, HttpResponse *resp)
    {
        if (IsFileHandler(req)) 
        {
            return FileHandler(req, resp);
        }
        if (req._method == "GET" || req._method == "HEAD") 
        {
            return Dispatcher(req, resp, _get_route);
        }
        else if (req._method == "PUT")
        {
            return Dispatcher(req, resp, _put_route);
        }
        else if (req._method == "DELETE")
        {
            return Dispatcher(req, resp, _delete_route);
        }
        else if (req._method == "POST")
        {
            return Dispatcher(req, resp, _post_route);
        }

        resp->GetState() = 405;
        return false;                                                                          
    }

    void OnConnected(const PtrConn &conn)
    {
        conn->SetContext(HttpContent());
        DBG_LOG("connected a new connection: %p", conn.get());
    }

    void OnMessage(const PtrConn &conn, Buffer * buf)
    {
        while (buf->ReadAbleSize() > 0)
        {
            HttpContent *context = std::any_cast<HttpContent>(&(conn->GetContext()));
            //通过上下文对缓冲区数据解析，也就是说， context里面有一个recv resp的函数， 然后接收到resp的信息， 就能把数据放到context的
            //req的成员里面
            context->RecvHttpRequest(buf);     //传入一个缓冲区， 对缓冲区中的数据进行解析， 得到的数据放到request中
            HttpRequest req = context->GetHttpRequest(); 
            HttpResponse resp(context->GetRespState());
            if (resp.GetState() > 400)  
            {
                ERR_LOG("error, %d", context->GetRespState());
                
                ErrorHandler(&resp);
                WriteResponse(conn, req, &resp);
                buf->ReaderMove(buf->ReadAbleSize());
                conn->ShutDown();
                return;
            }
            
            if (context->GetRecvState() != RECV_HTTP_OVER)
            {
                DBG_LOG("_________________________________________________________, %d", context->GetRecvState());
                return ;
            }
            //走到这， 说明是一个合理的请求
            Route(req, &resp);
            WriteResponse(conn, req, &resp);

            context->Reset();

            if (resp.IsColse())  //如果是一个短链接， 那么就关闭链接。
            {
                DBG_LOG("is close");
                conn->ShutDown();
            }
        }
    }

public: 

    HttpServer(int port, int timeout = 5)
        :_server(port)
    {
        _server.EnableInactiveConnectDestroy(timeout);
        _server.SetMessageCallBack(std::bind(&HttpServer::OnMessage, this, std::placeholders::_1, std::placeholders::_2));
        _server.SetConnectedCallBack(std::bind(&HttpServer::OnConnected, this, std::placeholders::_1));
    }

    void SetBaseDir(const std::string &path)
    {
        if (!Util::Is_Dir(path))
        {
            ERR_LOG("setbasedir error");
            return;
        }

        _basedir = path;
    }

    void Get(const std::string &pattern, Handler handler)
    {
        _get_route.push_back({std::regex(pattern), handler});
    }

    void Put(const std::string &pattern, Handler handler)
    {
        _put_route.push_back({std::regex(pattern), handler});
    }

    void Delete(const std::string &pattern, Handler handler)
    {
        _delete_route.push_back({std::regex(pattern), handler});
    }

    void Post(const std::string &pattern, Handler handler)
    {
        _post_route.push_back({std::regex(pattern), handler});
    }

    void SetThreadCount(int count)
    {
        _server.SetThreadPool(count);
    }

    void Listen()
    {
        _server.Start();
    }
};



